package pl.edu.agh.hollonCommision;

import java.io.File;

import javax.swing.JFileChooser;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.zest.core.viewers.AbstractZoomableViewer;
import org.eclipse.zest.core.viewers.GraphViewer;
import org.eclipse.zest.core.viewers.IZoomableWorkbenchPart;
import org.eclipse.zest.core.viewers.ZoomContributionViewItem;
import org.eclipse.zest.core.widgets.ZestStyles;
import org.eclipse.zest.layouts.LayoutStyles;
import org.eclipse.zest.layouts.algorithms.DirectedGraphLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.GridLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.RadialLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.SpringLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;

import pl.edu.agh.hollonCommision.graph.GraphModel;
import pl.edu.agh.hollonCommision.graph.PromptDistanceDialog;
import pl.edu.agh.hollonCommision.graph.PromptTimeAndDistanceDialog;
import pl.edu.agh.hollonCommision.graph.ZestGraph;
import pl.edu.agh.hollonCommision.graph.connectionModel.DeliveryLocationProximityConnection;
import pl.edu.agh.hollonCommision.graph.connectionModel.LocationAndTimeProximityConnection;
import pl.edu.agh.hollonCommision.graph.connectionModel.LocationProximityConnection;
import pl.edu.agh.hollonCommision.graph.connectionModel.PickupLocationProximityConnection;
import pl.edu.agh.hollonCommision.graph.metrics.BetweneesCentrality;
import pl.edu.agh.hollonCommision.graph.metrics.PageRank;
import pl.edu.agh.hollonCommision.graph.metrics.VertexDegree;
import dtp.commission.Commission;
import dtp.commission.TxtFileReader;

public class View extends ViewPart {
	public static final String ID = "GraphGenerationTest.view";

	private GraphViewer viewer;
	private Commission[] comms;
	private String benchmarkDir = "/home/gumek/workspace/Agenty/NewHolonicDispatchRider/benchmarks/";
	double defaultDistance = 5.0;
	private GraphModel model;
	private String choosenFileName = "lc101.txt";
	private String metricName = "NONE";
	private String graphGenerationRuleName = "Delivery Location Proximity";
	private Label fileNameLabel;
	private Label metricNameLabel;
	private Label graphGenerationRuleNameLabel;  
	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void createPartControl(Composite parent) {
		TabFolder tabFolder = new TabFolder (parent, SWT.NONE);
		TabItem graphTab =  new TabItem(tabFolder, SWT.NONE);
		Composite graphTabComposite = generateGraphTabComposite(tabFolder);
		graphTab.setText("Graph Visualization");
		graphTab.setControl(graphTabComposite);
		
		TabItem metricsTab =  new TabItem(tabFolder, SWT.NONE);
		Composite metricTabComposite = generateMetricsTabComposite(tabFolder);
		metricsTab.setText("Graph Metrics");
		metricsTab.setControl(graphTabComposite);

		comms = TxtFileReader
				.getCommissions(benchmarkDir + "pdp_100/lc101.txt");

		model = GraphModel.getGraph(comms,
				new DeliveryLocationProximityConnection(defaultDistance));

		viewer.setNodeStyle(ZestStyles.NODES_NO_LAYOUT_RESIZE);
		viewer.setLayoutAlgorithm(new RadialLayoutAlgorithm());
		generateZestGraph(model);
		viewer.setInput(new Object());

		addContextMenu();
		getViewSite().getActionBars().getToolBarManager().add(
				new ZoomContributionViewItem(new IZoomableWorkbenchPart() {

					@Override
					public AbstractZoomableViewer getZoomableViewer() {
						return viewer;
					}
				}));

		/*for (Commission c : comms) {
			System.out.println(c.getID() + " " + c.getDeliveryX() + " "
					+ c.getDeliveryY());
		}*/
	}

	private Composite generateMetricsTabComposite(Composite parent) {
		// TODO Auto-generated method stub
		return null;
	}

	private Composite generateGraphTabComposite(Composite tabFolder) {
		Composite graphTabComposite = new Composite(tabFolder, SWT.NONE);
		GridLayout gLayout = new GridLayout();
		GridData gData =  new GridData();
		GridData gd =  new GridData();
		gd.horizontalAlignment =  GridData.FILL;
		gLayout.numColumns = 3;
		gLayout.makeColumnsEqualWidth =  true;
		graphTabComposite.setLayout(gLayout);
		fileNameLabel = new Label(graphTabComposite, SWT.FILL);
		fileNameLabel.setText("Actual data file: " + choosenFileName);
		fileNameLabel.setLayoutData(gd);
		metricNameLabel = new Label(graphTabComposite, GridData.FILL);
		metricNameLabel.setLayoutData(gd);
		metricNameLabel.setText("Metric choosen: " + metricName);
		metricNameLabel.setData(gd);
		graphGenerationRuleNameLabel =  new Label(graphTabComposite, SWT.FILL);
		graphGenerationRuleNameLabel.setText("Graph gneerated with rule: " + graphGenerationRuleName);
		Composite graphComposite =  new Composite(graphTabComposite, SWT.FILL);
		gData.horizontalAlignment = GridData.FILL;
		gData.verticalAlignment = GridData.FILL;
		gData.grabExcessHorizontalSpace = true;
		gData.grabExcessVerticalSpace = true;
		gData.horizontalSpan = 3;
		graphComposite.setLayout(new FillLayout());
		graphComposite.setLayoutData(gData);
		viewer = new GraphViewer(graphComposite, SWT.NONE);
		return graphTabComposite;
	}

	private void generateZestGraph(GraphModel modelToGenerate) {
		ZestGraph zestGraph = new ZestGraph(modelToGenerate);
		viewer.setContentProvider(zestGraph);
		viewer.setLabelProvider(zestGraph);
		viewer.applyLayout();
		viewer.refresh();
	}

	private void addContextMenu() {
		MenuManager contextManager = new MenuManager();
		contextManager.setRemoveAllWhenShown(true);
		contextManager.addMenuListener(new IMenuListener() {

			@Override
			public void menuAboutToShow(IMenuManager manager) {
				manager.add(new Action("SelectDataFile") {
					public void run() {
						JFileChooser fc = new JFileChooser(benchmarkDir);
						int rc = fc.showDialog(null, "Select Data File");
						if (rc == JFileChooser.APPROVE_OPTION) {
							File file = fc.getSelectedFile();
							comms = TxtFileReader.getCommissions(file.getAbsolutePath());
							model = GraphModel.getGraph(comms,
									new LocationProximityConnection(defaultDistance));
							generateZestGraph(model);
							choosenFileName = file.getName();
							fileNameLabel.setText("Actual data file: " + choosenFileName);
						}
					}
				});

				MenuManager layoutSubMenu = generateChangeLayoutSubMenu();
				MenuManager graphsSubMenu = generateDifferentGraphSubMenu();
				MenuManager metricsSubMenu = generateMetricsSubMenu();
				manager.add(layoutSubMenu);
				manager.add(graphsSubMenu);
				manager.add(metricsSubMenu);
			}

		});
		Menu menu = contextManager.createContextMenu(viewer.getControl());
		viewer.getControl().setMenu(menu);
		getSite().registerContextMenu(contextManager, viewer);
	}

	@Override
	public void setFocus() {
		// TODO Auto-generated method stub

	}

	private MenuManager generateChangeLayoutSubMenu() {
		MenuManager subMenu = new MenuManager("ChangeLayout");
		subMenu.add(new Action("Radial layout") {
			public void run() {
				viewer.setLayoutAlgorithm(new RadialLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING), false);
				viewer.applyLayout();
				viewer.refresh();
			}
		});
		subMenu.add(new Action("Spring layout") {
			public void run() {
				viewer.setLayoutAlgorithm((new SpringLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING)));
				viewer.applyLayout();
				viewer.refresh();
			}
		});
		subMenu.add(new Action("Tree layout") {
			public void run() {
				viewer.setLayoutAlgorithm((new TreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING)));
				viewer.applyLayout();
				viewer.refresh();
			}
		});
		subMenu.add(new Action("Grid layout") {
			public void run() {
				viewer.setLayoutAlgorithm((new GridLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING)));
				viewer.applyLayout();
				viewer.refresh();
			}
		});
		subMenu.add(new Action("Directed graph layout") {
			public void run() {
				viewer.setLayoutAlgorithm((new DirectedGraphLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING)));
				viewer.applyLayout();
				viewer.refresh();
			}
		});
		return subMenu;
	}

	private MenuManager generateDifferentGraphSubMenu() {
		MenuManager subMenu = new MenuManager("generateGraph");
		subMenu.add(new Action("PickupLocalizationProximity") {
			public void run() {
				PromptDistanceDialog d = new PromptDistanceDialog(null);
				d.create();
				if (d.open() == Window.OK) {
					model = GraphModel.getGraph(comms,
							new PickupLocationProximityConnection(d
									.getDistance()));
					generateZestGraph(model);
					graphGenerationRuleName = "Pickup Location Proximity";
					graphGenerationRuleNameLabel.setText("Graph gneerated with rule: " + graphGenerationRuleName);
				}
			}
		});
		subMenu.add(new Action("DeliveryLocalizationProximity") {
			public void run() {
				PromptDistanceDialog d = new PromptDistanceDialog(null);
				d.create();
				if (d.open() == Window.OK) {
					model = GraphModel.getGraph(comms,
							new DeliveryLocationProximityConnection(d
									.getDistance()));
					generateZestGraph(model);
					graphGenerationRuleName = "Delivery Location Proximity";
					graphGenerationRuleNameLabel.setText("Graph gneerated with rule: " + graphGenerationRuleName);
				}
			}
		});
		subMenu.add(new Action("PickupOrDeliveryLocalizationProximity") {
			public void run() {
				PromptDistanceDialog d = new PromptDistanceDialog(null);
				d.create();
				if (d.open() == Window.OK) {
					model = GraphModel.getGraph(comms,
							new LocationProximityConnection(d.getDistance()));
					generateZestGraph(model);
					graphGenerationRuleName = "Pickup or Delivery Location Proximity";
					graphGenerationRuleNameLabel.setText("Graph gneerated with rule: " + graphGenerationRuleName);
				}
			}
		});
		subMenu.add(new Action("LocationAndTimeProximity") {
			public void run() {
				PromptTimeAndDistanceDialog d = new PromptTimeAndDistanceDialog(null);
				d.create();
				if (d.open() == Window.OK) {
					System.out.println("result " + d.getDistance()+" "+ d.getTime());
					model = GraphModel.getGraph(comms,
							new LocationAndTimeProximityConnection(d.getDistance(), d.getTime()));
					generateZestGraph(model);
					graphGenerationRuleName = "Location and Time Proximity";
					graphGenerationRuleNameLabel.setText("Graph gneerated with rule: " + graphGenerationRuleName);
				}
			}
		});
		return subMenu;
	}
	
	protected MenuManager generateMetricsSubMenu() {
		MenuManager subMenu = new MenuManager("Aply metric");
		subMenu.add(new Action("Node degree") {
			public void run() {
				VertexDegree metric = new VertexDegree();
				metric.calculateMetric(model);
				metricName = "Node degree";
				metricNameLabel.setText("Metric choosen: " + metricName);
				viewer.applyLayout();
				viewer.refresh();
			}
		});
		subMenu.add(new Action("Betweness Centrality") {
			public void run() {
				BetweneesCentrality metric = new BetweneesCentrality();
				metric.calculateMetric(model);
				metricName = "Betweness Centrality";
				metricNameLabel.setText("Metric choosen: " + metricName);
				viewer.applyLayout();
				viewer.refresh();
			}
		});
		subMenu.add(new Action("Page Rank") {
			public void run() {
				PageRank metric = new PageRank();
				metric.calculateMetric(model);
				metricName = "Page Rank";
				metricNameLabel.setText("Metric choosen: " + metricName);
				viewer.applyLayout();
				viewer.refresh();

			}
		});
		return subMenu;
	}
}